﻿namespace DimensionsHelper.Client.WinUi.ViewModels;

public abstract partial class RecordHistoryViewModel : ObservableObject
{
    protected RecordHistoryViewModel()
    {
        CurrentFileName = string.Empty;
        _optionFileService = App.GetService<IOptionalFileService>();
        HistoricalList = [];
        App.RegisterViewModel(this);
    }


    private readonly IOptionalFileService _optionFileService;


    private IOptionalFileService GetInitializedOptionFileService()
    {
        if (string.IsNullOrEmpty(_optionFileService.Key))
        {
            // 初始化预设文件和历史文件
            _optionFileService.Key = SettingsKey;
            InitializeHistoricalList(App.HistoryKeptNumber);
        }

        return _optionFileService;
    }


    protected bool UpdatingInternal
    {
        get;
        set;
    }


    public abstract string Section
    {
        get;
    }


    protected abstract string SettingsKey
    {
        get;
    }


    protected abstract string[] FileFilters
    {
        get;
    }


    public OptionalFileViewModel? SelectedOptionalFile
    {
        get;
        protected set;
    }


    [ObservableProperty]
    public partial string CurrentFileName
    {
        get;
        set;
    }


    protected IOptionalFileService OptionalFileService => GetInitializedOptionFileService();


    public ObservableCollection<OptionalFileViewModel> HistoricalList
    {
        get;
    }


    ~RecordHistoryViewModel()
    {
        App.UnregisterViewModel(this);
    }


    public event Action<OptionalFileViewModel>? HistoryAdded;

    public event Action? HistoryCleared;


    public void OnAppPropertyChanged(string propertyName, object value)
    {
        if (propertyName == nameof(App.HistoryKeptNumber))
        {
            HistoricalList.Clear();
            InitializeHistoricalList((int)value);
        }

        OnAppPropertyChangedOverride(propertyName, value);
    }


    protected virtual void OnAppPropertyChangedOverride(string propertyName, object value)
    {
    }


    async partial void OnCurrentFileNameChanged(string value)
    {
        try
        {
            if (UpdatingInternal)
            {
                return;
            }

            if (SelectedOptionalFile != null &&
                !SelectedOptionalFile.FileName.Equals(value, StringComparison.OrdinalIgnoreCase))
            {
                SelectedOptionalFile.IsSelected = false;
            }

            if (await OnCurrentFileNameChangedOverride(value))
            {
                AddHistoryAsync(value);
            }
        }
        catch (Exception e)
        {
            await App.ShowErrorMessage(e);
        }
    }


    protected async virtual Task<bool> OnCurrentFileNameChangedOverride(string value)
    {
        await Task.CompletedTask;
        return true;
    }


    [RelayCommand]
    private async Task SelectFile()
    {
        string? selected = await App.GetService<IFilePikerService>().PickSingleFileAsync(FileFilters);
        if (!string.IsNullOrEmpty(selected))
        {
            CurrentFileName = selected;
        }
    }


    [RelayCommand]
    protected abstract Task SaveFile();


    [RelayCommand]
    public async Task ClearHistoricalListAsync()
    {
        HistoricalList.Clear();
        await OptionalFileService.ClearHistoryAsync();
        OnHistoricalListClearedOverride();
        HistoryCleared?.Invoke();
    }


    protected virtual void OnHistoricalListClearedOverride()
    {
    }


    private async void InitializeHistoricalList(int size)
    {
        try
        {
            foreach (string history in (await OptionalFileService.GetHistoricalNamesAsync()).TakeLast(size))
            {
                AddHistory(history);
            }
        }
        catch (Exception e)
        {
            await App.ShowErrorMessage(e);
        }
    }


    private void AddHistory(string fileName)
    {
        OptionalFileViewModel viewModel = new()
        {
            FileName = fileName,
            RemoveHandler = HistoryRemoveHandler
        };

        viewModel.Selected += OnOptionalFileSelected;
        viewModel.Unselected += OnOptionalFileUnselected;

        HistoricalList.Add(viewModel);

        OnHistoryAddedOverride(viewModel);
        HistoryAdded?.Invoke(viewModel);
    }


    protected virtual void OnHistoryAddedOverride(OptionalFileViewModel viewModel)
    {
    }


    protected async void AddHistoryAsync(string fileName)
    {
        try
        {
            if (string.IsNullOrEmpty(fileName) || await OptionalFileService.IsHistoryAsync(fileName))
            {
                return;
            }

            if (!App.GetService<IFileService>().Exists(fileName))
            {
                return;
            }

            AddHistory(fileName);
            await OptionalFileService.AddHistoryAsync(fileName);
        }
        catch (Exception e)
        {
            await App.ShowErrorMessage(e);
        }
    }


    private void HistoryRemoveHandler(OptionalFileViewModel sender) => HistoricalList.Remove(sender);


    protected void OnOptionalFileSelected(OptionalFileViewModel sender)
    {
        UpdatingInternal = true;

        if (SelectedOptionalFile != null)
        {
            SelectedOptionalFile.IsSelected = false;
        }

        UpdatingInternal = false;

        SelectedOptionalFile = sender;
        CurrentFileName = sender.FileName;
    }


    protected void OnOptionalFileUnselected(OptionalFileViewModel sender)
    {
        if (UpdatingInternal)
        {
            return;
        }

        UpdatingInternal = true;
        SelectedOptionalFile = null;
        CurrentFileName = string.Empty;
        UpdatingInternal = false;
    }
}